{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id='HOME'></a>\n",
    "# CHAPTER 3 Py Filling: Lists, Tuples, Dictionaries, and Sets\n",
    "## Python容器：串列、Tuples、字典與集合\n",
    "\n",
    "* [3.1 串列(list)與Tuples](#Lists_Tuples)\n",
    "* [3.2 串列(list)型態](#Lists)\n",
    "* [3.3 Tuples型態](#Tuples)\n",
    "* [3.4 字典(Dictionarie)型態](#Dictionaries)\n",
    "* [3.5 集合(set)型態](#Sets)\n",
    "* [3.6 比較型態差別](#CompareDataStructures)\n",
    "* [3.7 建立大型結構](#MakeBiggerDataStructures)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "------\n",
    "<a id='Lists_Tuples'></a>\n",
    "## 3.1 串列(list)與Tuples\n",
    "[回目錄](#HOME)\n",
    "\n",
    "兩者差異在於，List可以改變其內容，增減長度 or 替換等等皆可以  \n",
    "Tuples一旦賦予值之後，就不能再修改。  \n",
    "以效能和記憶體使用量來說，Tuples皆較佳"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "------\n",
    "<a id='Lists'></a>\n",
    "## 3.2 串列(list)型態\n",
    "[回目錄](#HOME)\n",
    "\n",
    "List可以使用 **[]** 或是 **list()** 來創建空的，或是直接加入值進去，使用逗號區分即可。內容可以重複出現，且具有順序性。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[]\n",
      "['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']\n",
      "['emu', 'ostrich', 'cassowary']\n",
      "['Graham', 'John', 'Terry', 'Terry', 'Michael']\n"
     ]
    }
   ],
   "source": [
    "empty_list = []\n",
    "weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']\n",
    "big_birds = ['emu', 'ostrich', 'cassowary']\n",
    "first_names = ['Graham', 'John', 'Terry', 'Terry', 'Michael']\n",
    "\n",
    "print(empty_list)\n",
    "print(weekdays)\n",
    "print(big_birds)\n",
    "print(first_names)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以使用 **list()** 來作為轉換其他型別至List，或是前面2.3小節提到的字串__split()__函數"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['c', 'a', 't']\n",
      "['ready', 'fire', 'aim']\n",
      "['1', '6', '1952']\n"
     ]
    }
   ],
   "source": [
    "print(list('cat'))\n",
    "\n",
    "a_tuple = ('ready', 'fire', 'aim')\n",
    "print(list(a_tuple))\n",
    "\n",
    "birthday = '1/6/1952'\n",
    "print((birthday.split('/')))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "提取內容時跟字串一樣使用[]，  \n",
    "**index** 從0開始，-1為最後一個，  \n",
    "**index** 數值的範圍請務必在總長度內，不然會出現IndexError。也可以將其修改替換內容。  \n",
    "提取多個以上也如同字串中的用法 __[start : end : step]__，注意這邊只會提取到index為end - 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a\n",
      "b\n",
      "d\n",
      "c\n",
      "['QQ', 'b']\n",
      "[]\n",
      "['QQ', 'c']\n"
     ]
    }
   ],
   "source": [
    "XD = ['a', 'b', 'c', 'd']\n",
    "print(XD[0])\n",
    "print(XD[1])\n",
    "print(XD[-1])\n",
    "print(XD[-2])\n",
    "\n",
    "XD[0] = 'QQ'\n",
    "\n",
    "print(XD[0:2])\n",
    "print(XD[2:-2])\n",
    "print(XD[::2])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "List裡面可以包含不同類型的物件，當然也包括List"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['a', 'b', 'c']\n",
      "b\n"
     ]
    }
   ],
   "source": [
    "XD = [['a', 'b', 'c'],['d', 'e', 'f'],['g', 'h', 'i']]\n",
    "print(XD[0])\n",
    "print(XD[0][1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以使用List的內建函數append()來向後面添加元素\n",
    "\n",
    "|語法|效果|\n",
    "|--|--|\n",
    "|**list.extend()**或 **+=** |合併list|\n",
    "|**list.insert()**|在指定位置插入元素，如果位置超過最大長度則放在最後面，故不會飛到很遠去或出錯。|\n",
    "|**del Object** |用來刪除某個位置的元素，剩餘元素會自動往前補填補|\n",
    "|**list.remove()**|用來移除指定元素|\n",
    "|**list.pop()**|為類似剪出的效果，可以將指定位置的元素剪出來，預設index為 -1|\n",
    "|**list.index()**|找查指定元素第一次出現的index|\n",
    "|**in Object** |判斷指定元素是否存在|\n",
    "|**list.count()**|計算指定元素出現次數|\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['a', 'b'] ['e', 'f']\n",
      "['a', 'b', 'QQ~']\n",
      "['a', 'b', 'QQ~', 'e', 'f']\n",
      "['a', 'b', 'QQ~', 'e', 'f', 'e', 'f']\n",
      "['a', 'b', 'QQ~', 'e', 'f', 'e', 'f', ['e', 'f']]\n",
      "['a', 'b', 'c', 'QQ~', 'e', 'f', 'e', 'f', ['e', 'f']]\n",
      "['a', 'b', 'c', 'QQ~', 'e', 'f', 'e', 'f', ['e', 'f'], 'ker']\n",
      "['a', 'b', 'c', 'QQ~', 'e', 'f', 'e', 'f', 'ker']\n",
      "['a', 'b', 'c', 'QQ~', 'f', 'e', 'f', 'ker']\n",
      "['a', 'b', 'c', 'f', 'e', 'f', 'ker'] QQ~\n",
      "3\n",
      "True\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "XD = ['a', 'b']\n",
    "XD2 = ['e', 'f']\n",
    "print(XD, XD2)\n",
    "\n",
    "XD.append('QQ~')\n",
    "print(XD)\n",
    "\n",
    "XD.extend(XD2)\n",
    "print(XD)\n",
    "\n",
    "XD += XD2\n",
    "print(XD)\n",
    "\n",
    "XD.append(XD2)\n",
    "print(XD)\n",
    "\n",
    "XD.insert(2, 'c')\n",
    "print(XD)\n",
    "\n",
    "XD.insert(500, 'ker')\n",
    "print(XD)\n",
    "\n",
    "del XD[8]\n",
    "print(XD)\n",
    "\n",
    "XD.remove('e')\n",
    "print(XD)\n",
    "\n",
    "QQ = XD.pop(3)\n",
    "print(XD, QQ)\n",
    "\n",
    "print(XD.index('f'))\n",
    "print('ker' in XD)\n",
    "print(XD.count('f'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "前面2.3節提到的__string.join()__，可以用來組裝List成為字串，  \n",
    "書中提到這邊的用法看起來有點彆扭，如果改成__List.join(', ')__會更直覺，  \n",
    "但是當初設計的理念就是join的方法是在字串的型態中，  \n",
    "這樣後面我想要針對List、Tuples或是字串使用字串做組裝，就只要一種方法就好，  \n",
    "不用針對每種型態都去設計一個相同的方法來做使用，如下面範例所示範。  \n",
    "__string.join()__ 與 __string.split()__兩個為相對應的用法!!!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a, b, c\n",
      "a, b, c\n",
      "a, b, c\n",
      "['a', 'b', 'c']\n"
     ]
    }
   ],
   "source": [
    "print(', '.join(['a', 'b', 'c']))\n",
    "print(', '.join('abc'))\n",
    "print(', '.join(('a', 'b', 'c')))\n",
    "print('a, b, c'.split(', '))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* **list.sort()**為list排序方法，\n",
    "* **sorted()**為通用的排序函數\n",
    "其中的差異在於__sort()__會直接改變輸入的list，__sorted()__則會另外回傳一個排序好的物件，\n",
    "\n",
    "**len()**可以獲得list的長度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['a', 'b', 'c']\n",
      "['a', 'b', 'c']\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "L = ['b', 'c', 'a']\n",
    "L.sort()\n",
    "print(L)\n",
    "\n",
    "t = ['b', 'c', 'a']\n",
    "a = sorted(t)\n",
    "print(a)\n",
    "\n",
    "print(len(a))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用 '=' 設定變數則會是傳址，等同於前面說的標籤概念，把兩張標籤貼在同一個物件上(number or srting 除外)  \n",
    "這樣當我改變了物件後，則物件上所有的標籤所指到的值都會跟著改變，  \n",
    "若要改成傳值的話可以使用**copy()** 、 **list.list()** 與 **list[:]** 來達到目的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[4, 2, 3] [4, 2, 3]\n",
      "['surprises', 2, 3] ['surprises', 2, 3] [4, 2, 3] [4, 2, 3] [4, 2, 3]\n"
     ]
    }
   ],
   "source": [
    "a = [1, 2, 3]\n",
    "b = a\n",
    "\n",
    "a[0] = 4\n",
    "print(a, b)\n",
    "\n",
    "c = a.copy()\n",
    "d = list(a)\n",
    "e = a[:]\n",
    "a[0] = 'surprises'\n",
    "print(a, b, c, d, e)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "------\n",
    "<a id='Tuples'></a>\n",
    "## 3.3 Tuples型態\n",
    "[回目錄](#HOME)\n",
    "\n",
    "也是一個List差別只在不能做修改，一旦给定後，無法再進行增加 刪除 修改等操作，所以可以當作一個常數的List\n",
    "\n",
    "創建時空的時使用()，一個以上時可以省略，但是一個時最後一個逗號不可以省略。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "()\n",
      "('tem',)\n",
      "('tem1', 'tem2', 'tem3')\n",
      "tem1 tem2 tem3\n"
     ]
    }
   ],
   "source": [
    "a = ()   #空Tuples\n",
    "b = 'tem', #b:(tem,) 括弧可以省略，但是一個的時候逗號不能省略\n",
    "c = 'tem1', 'tem2', 'tem3'  #('tem1', 'tem2', 'tem3')\n",
    "d, e, f = c   #d:'tem1', e:'tem2', f:'tem3'\n",
    "\n",
    "print(a)\n",
    "print(b)\n",
    "print(c)\n",
    "print(d, e, f)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "結合以上的用法可以有一個超級方便直覺的用法，任意交換變數間的值。  \n",
    "(在等號右邊的東西會先形成一個Tuples，再分配給前面的變數。)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3 1 2\n"
     ]
    }
   ],
   "source": [
    "a = '1'\n",
    "b = '2'\n",
    "c = '3'\n",
    "b, c, a = a, b, c\n",
    "\n",
    "print(a, b, c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "既然他不能修改等等的那相對於List一定也有其他好處\n",
    "\n",
    "* 空間較小\n",
    "* 不會不小心修改到值\n",
    "* 可以當作dictionary的key值 (後一小節有說明)\n",
    "* 命名Tuples，可以做為物件的替代 (第六章會說明)\n",
    "* 函數的傳遞是以Tuples形式傳遞\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "------\n",
    "<a id='Dictionaries'></a>\n",
    "## 3.4 字典型態\n",
    "[回目錄](#HOME)\n",
    "\n",
    "為一種沒有順序的容器，其使用的是大括弧{}，裏頭包含鍵值與值(**key : value**)  \n",
    "可以使用**dict()**來轉換期他型態至dictionary\n",
    "\n",
    "|語法|效果|\n",
    "|--|--|\n",
    "|**D.update()**  |  合併不同dictionary|\n",
    "|**del Object**  |     刪除某項|\n",
    "|**in Object**  |      是否存在裡面(key)|\n",
    "|**D.keys()  **  |    獲得所有key值|\n",
    "|**D.values()**  |   獲得所有value值|\n",
    "|**D.items() **  |    獲得全部的key: value( Tuples型態 )|\n",
    "|**D.copy()  **  |    複製一個dictionary|\n",
    "|**D.clear() **  |     清除所有內容|"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'a': 'v', 'b': 'w'} {'d': 'y', 'c': 'x'}\n",
      "{'e': 'f', 'a': 'b', 'c': 'd'} {'e': 'f', 'a': 'b', 'c': 'd'} {'e': 'f', 'a': 'b', 'c': 'd'}\n",
      "{'e': 'f', 'a': 'b', 'c': 'd'} {'e': 'f', 'a': 'b', 'c': 'd'}\n",
      "============分隔線============\n",
      "x\n",
      "z\n",
      "{'d': 'y', 'a': 'v', 'c': 'z', 'b': 'w'}\n",
      "{'a': 'v', 'c': 'z', 'b': 'w'}\n",
      "True\n",
      "============分隔線============\n",
      "dict_keys(['a', 'c', 'b'])\n",
      "dict_values(['v', 'z', 'w'])\n",
      "[('a', 'v'), ('c', 'z'), ('b', 'w')]\n",
      "============分隔線============\n",
      "{'a': 'n', 'c': 'z', 'b': 'w'} {'a': 'n', 'c': 'z', 'b': 'w'}\n",
      "{'a': 'n', 'c': 'z', 'b': 'w'} {'a': 'm', 'c': 'z', 'b': 'w'}\n",
      "{}\n"
     ]
    }
   ],
   "source": [
    "dic = { 'a':'v','b':'w', }  #最後一個逗號可以省略\n",
    "dic_ = { 'd':'y','c':'x' }  #最後一個逗號可以省略\n",
    "print(dic, dic_)\n",
    "\n",
    "\n",
    "lol1 = [ ['a', 'b'], ['c', 'd'], ['e', 'f'] ]\n",
    "lol2 = [ ('a', 'b'), ('c', 'd'), ('e', 'f') ]\n",
    "lol3 = ( ['a', 'b'], ['c', 'd'], ['e', 'f'] )\n",
    "print(dict(lol1), dict(lol2), dict(lol3))\n",
    "\n",
    "\n",
    "tos1 = [ 'ab', 'cd', 'ef' ]\n",
    "tos2 = ( 'ab', 'cd', 'ef' )\n",
    "print(dict(tos1), dict(tos2))\n",
    "\n",
    "print('============分隔線============')\n",
    "print(dic_['c'])\n",
    "dic_['c'] = 'z'\n",
    "print(dic_['c'])\n",
    "\n",
    "dic.update(dic_)\n",
    "print(dic)\n",
    "\n",
    "\n",
    "del dic['d']\n",
    "print(dic)\n",
    "\n",
    "print('a' in dic)\n",
    "\n",
    "print('============分隔線============')\n",
    "print(dic.keys())         # dict_keys(['a', 'b', 'c'])\n",
    "print(dic.values())       # ['v', 'w', 'x']\n",
    "print(list(dic.items()))  # [('a', 'v'), ('b', 'w'), ('c', 'x')]\n",
    "\n",
    "print('============分隔線============')\n",
    "dic_new = dic\n",
    "dic_new['a'] = 'n'\n",
    "print(dic, dic_new)\n",
    "\n",
    "dic_cp = dic.copy()\n",
    "dic_cp['a'] = 'm'\n",
    "print(dic, dic_cp)\n",
    "\n",
    "dic.clear() \n",
    "print(dic)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "------\n",
    "<a id='Sets'></a>\n",
    "## 3.5 集合型態\n",
    "[回目錄](#HOME)\n",
    "\n",
    "集合就好比沒有value的dictionary，一樣沒有順序，使用大括弧**{}**。  \n",
    "空白集合為**set()**，也合相當於False。  \n",
    "使用**set()**可以轉換其他型態至集合，dictionary轉換至set只會保留key值。  \n",
    "**in**也可以檢查特定元素是否存在其中。\n",
    "\n",
    "![Alt text](http://i.imgur.com/gXChbwA.png \"集合示意圖\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "set() {8, 0, 2, 4, 6}\n",
      "{'r', 'e', 'l', 't', 's'}\n",
      "{'D', 'M', 'P', 'A'}\n",
      "{'U', 'Echoes', 'Atom'}\n",
      "{'orange', 'apple'}\n"
     ]
    }
   ],
   "source": [
    "empty_set = set()\n",
    "even_numbers = {0, 2, 4, 6, 8}\n",
    "print(empty_set, even_numbers)\n",
    "\n",
    "\n",
    "print(set( 'letters' ))\n",
    "print(set( ['D', 'A', 'P', 'M'] ))\n",
    "print(set( ('U', 'Echoes', 'Atom') ))\n",
    "print(set( {'apple': 'red', 'orange': 'orange'} ))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "------\n",
    "<a id='CompareDataStructures'></a>\n",
    "## 3.6 比較型態差別\n",
    "[回目錄](#HOME)\n",
    "\n",
    "比較不同容器之間的使用差別，請自己在看過一次書中介紹。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "------\n",
    "<a id='MakeBiggerDataStructures'></a>\n",
    "## 3.7 建立大型結構\n",
    "[回目錄](#HOME)\n",
    "\n",
    "容器中可以包含不同型態的元素，也可以包含其他的容器物件。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'Pythons': ['Chapman', 'Cleese', 'Gilliam', 'Jones', 'Palin'], 'Marxes': ['Groucho', 'Chico', 'Harpo'], 'Stooges': ['Moe', 'Curly', 'Larry']}\n",
      "['Groucho', 'Chico', 'Harpo']\n",
      "Chico\n"
     ]
    }
   ],
   "source": [
    "dict_of_lists = {'Stooges': ['Moe', 'Curly', 'Larry'],\n",
    "                'Marxes': ['Groucho', 'Chico', 'Harpo'],\n",
    "                'Pythons': ['Chapman', 'Cleese', 'Gilliam', 'Jones', 'Palin']}\n",
    "\n",
    "print(dict_of_lists)\n",
    "print(dict_of_lists['Marxes'])\n",
    "print(dict_of_lists['Marxes'][1])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [Root]",
   "language": "python",
   "name": "Python [Root]"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
